package com.duobaoyu.dby.supply.biz.strategy.message.order.logistics;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.duobaoyu.dby.channel.adapter.bean.message.order.OrderMessage;
import com.duobaoyu.dby.channel.adapter.enums.BizMessageTypeEnum;
import com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.order.OrderStatusEnum;
import com.duobaoyu.dby.channel.strategy.supply.impl.real.xingyun.callback.order.XingYunOrderDeliverCallback;
import com.duobaoyu.dby.supply.biz.constant.OperateSourceConstants;
import com.duobaoyu.dby.supply.biz.constant.OrderOperateConstants;
import com.duobaoyu.dby.supply.biz.service.order.OrderService;
import com.duobaoyu.dby.supply.biz.strategy.message.order.base.BaseOrderAsyncHandler;
import com.duobaoyu.dby.supply.common.biz.bo.message.ChannelMessageBO;
import com.duobaoyu.dby.supply.db.entity.extend.OrderProductResultExtendInfo;
import com.duobaoyu.dby.supply.db.entity.order.Order;
import com.duobaoyu.dby.supply.db.entity.order.OrderLogistics;
import com.duobaoyu.dby.supply.db.entity.order.OrderProduct;
import com.duobaoyu.dby.supply.db.repository.order.OrderLogisticsRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderProductRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderRepository;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 物流消息同步
 *
 * @author fengshaoyu
 * @version 1.0.0
 * @date 2023/10/21 10:43
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class XingYunLogisticsOrderInfoAsyncHandler extends BaseOrderAsyncHandler {

	private final OrderService orderService;
	private final OrderRepository orderRepository;
	private final OrderLogisticsRepository orderLogisticsRepository;
	private final TransactionTemplate transactionTemplate;
	private final OrderProductRepository orderProductRepository;

	@Override
	protected Set<String> channelCodes() {
		return Sets.newHashSet(ChannelCodeEnum.XING_YUN.getValue());
	}

	@Override
	protected Set<Integer> bizMessageTypes() {
		return Sets.newHashSet(BizMessageTypeEnum.LOGISTICS_STATUS_CHANGE.getValue());
	}

	@Override
	protected Boolean executeHandler(ChannelMessageBO channelMessage, Object beforeResult) {
		OrderMessage orderMessage = JSON.parseObject(channelMessage.getMessage(), OrderMessage.class);
		String data = JSONObject.parseObject(channelMessage.getOriginalMessage()).getString("data");
		XingYunOrderDeliverCallback xingYunOrderDeliverCallback = JSON.parseObject(data, XingYunOrderDeliverCallback.class);
		List<XingYunOrderDeliverCallback.OrderExpress> orderExpressList = xingYunOrderDeliverCallback.getExpressList();
		List<String> orderSnAllList = new ArrayList<>();
		List<OrderProduct> orderProductAllList = new ArrayList<>();
		List<OrderLogistics> orderLogisticsList = new ArrayList<>();
		for (XingYunOrderDeliverCallback.OrderExpress orderExpress : orderExpressList) {
			for (XingYunOrderDeliverCallback.OrderSku orderSku : orderExpress.getSkuList()) {
				List<Order> orderList = orderRepository.getBaseMapper().selectList(Wrappers.<Order>lambdaQuery().in(Order::getChannelOrderSn, orderMessage.getChannelOrderSn())
						.eq(Order::getChannelCode, channelMessage.getChannelCode()));

				if (CollectionUtils.isEmpty(orderList)) {
					continue;
				}
				List<String> orderSnList = orderList.stream().map(Order::getOrderSn).collect(Collectors.toList());
				orderSnAllList.addAll(orderSnList);

				List<OrderProduct> orderProducts = orderProductRepository.getBaseMapper().selectList(Wrappers.<OrderProduct>lambdaQuery().in(OrderProduct::getOrderSn, orderSnList)
						.apply("FIND_IN_SET (" + orderSku.getSkuId() + ",REPLACE(channel_sku_code, '_', ','))"));

				List<OrderProduct> orderProductList = orderProducts.stream().peek(item -> {
					OrderProductResultExtendInfo resultExtend = item.getResultExtend();
					if(ObjectUtils.isEmpty(resultExtend)){
						resultExtend = new OrderProductResultExtendInfo();
					}
					resultExtend.setChannelExpressCode(orderExpress.getExpressCode());
					item.setResultExtend(resultExtend);
				}).collect(Collectors.toList());
				orderProductAllList.addAll(orderProductList);

				for (String orderSn:orderSnList) {
					OrderLogistics orderLogistics = new OrderLogistics();
					orderLogistics.setOrderSn(orderSn);
					orderLogistics.setDeliveryCarrier(orderExpress.getExpressCompany());
					orderLogistics.setDeliveryOrderSn(orderExpress.getExpressOrder());
					orderLogisticsList.add(orderLogistics);
				}
			}
		}

		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(@NotNull TransactionStatus transactionStatus) {
				OrderStatusEnum orderSubStatusOld = OrderStatusEnum.getOrderSubStatusEnum(OrderStatusEnum.WAIT_SHIP.getValue());
				OrderStatusEnum orderSubStatusNew = OrderStatusEnum.getOrderSubStatusEnum(OrderStatusEnum.SHIPPED.getValue());
				orderService.updateStatusByOrderSnList(orderSnAllList, orderSubStatusNew, orderSubStatusOld, OperateSourceConstants.OPERATION_CHANNEL, OrderOperateConstants.CHANNEL_PART_SEND,null);

				orderProductRepository.updateBatchById(orderProductAllList);
				orderLogisticsRepository.saveBatch(orderLogisticsList);
			}
		});
		return Boolean.TRUE;
	}
}
